let fetch = require('whatwg-fetch').fetch;
let qs = require('qs');

function Fetch(url, options = {}) {
  /* global fetch:true */
  return fetch(url, options);
}

function checkStatus(response) {
  if (response.status >= 200 && response.status < 300) {
    return Promise.resolve(response);
  }
  const error = new Error(response.statusText || response.status);
  error.response = response;
  return Promise.reject(error);
}

function bodyBuilder(data, type) {
  if (type === Fetch.Type.FORM) return qs.stringify(data, { arrayFormat: 'repeat' });
  if (type === Fetch.Type.JSON) return JSON.stringify(data);
  if (type === Fetch.Type.FORMDATA) return data;
  return null;
}

function responseProcessBuilder(type, fetchCall) {
  let response;
  return type === Fetch.Type.JSON ?
    fetchCall
      .then((res) => {
        response = res;
        return res.json();
      })
      .catch(() => Promise.reject(response && response.text())) :
    fetchCall;
}

function urlBuilder(url, query) {
  const fullurl = query ? [url, '?', qs.stringify(query)].join('') : url;
  return fullurl;
}


Fetch.Type = {
  JSON: 'application/json; charset=utf-8',
  FORM: 'application/x-www-form-urlencoded; charset=utf-8',
  FORMDATA: 'multipart/form-data; charset=utf-8',
};

Fetch.catchErr = (err) => {
  console.error(err);
  return 'err';
};

Fetch.jsonp = (url, options = {}) => {
  const query = options.query || {};
  const random = Math.floor(Math.random() * 100000);
  const timestamp = (new Date()).getTime();
  const callback = `FetchJSONPCallbackR${random}T${timestamp}`;

  const scriptTag = document.createElement('script');
  const head = document.getElementsByTagName('head')[0];

  scriptTag.Id = callback;

  const promise = new Promise((resolve, reject) => {
    window[callback] = (data) => {
      resolve(data);
      head.removeChild(scriptTag);
      window[callback] = null;
    };
    scriptTag.onerror = reject;
  });


  const fullUrl = urlBuilder(url, { ...query, jsonp_v: random, callback });
  scriptTag.src = fullUrl;
  head.appendChild(scriptTag);

  return promise;
};

Fetch.request = (url, options = {}, method = 'POST') => {
  const {
    data,
    query,
    ContentType = Fetch.Type.JSON,
    type = Fetch.Type.JSON,
    cors = false,
    headers = {},
  } = options;
  const fullUrl = urlBuilder(url, query);

  const body = bodyBuilder(data, ContentType);
  if (body === null) return Promise.reject('ContentType is not json/form-data/x-www-form-urlencoded');

  const fetchCall = fetch(fullUrl, {
    method,
    headers: {
      'Content-Type': ContentType,
      ...headers,
    },
    body,
    credentials: cors ? 'include' : 'same-origin',
  }).then(checkStatus);

  return responseProcessBuilder(type, fetchCall);
};

Fetch.post = (url, options = {}) => Fetch.request(url, options, 'POST');
Fetch.put = (url, options = {}) => Fetch.request(url, options, 'PUT');
Fetch.get = (url, options = {}) => Fetch.request(url, options, 'GET');

// if (typeof exports === 'object' && typeof module !== 'undefined') {
  module.exports = Fetch;
// } else {
  // export default Fetch;
// }

